package com.java.test;

import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.*;
import org.web3j.abi.datatypes.generated.*;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.gas.ContractGasProvider;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ERC20 extends Contract {

    // ERC20标准函数名
    public static final String FUNC_APPROVE = "approve";
    public static final String FUNC_TRANSFER = "transfer";
    public static final String FUNC_BALANCE_OF = "balanceOf";

    // 构造函数
    protected ERC20(String contractBinary, String contractAddress, Web3j web3j,
                    Credentials credentials, ContractGasProvider gasProvider) {
        super(contractBinary, contractAddress, web3j, credentials, gasProvider);
    }

    // 加载合约的静态方法
    public static ERC20 load(String contractAddress, Web3j web3j,
                             Credentials credentials, ContractGasProvider gasProvider) {
        return new ERC20("", contractAddress, web3j, credentials, gasProvider);
    }

    // approve方法实现
    public RemoteFunctionCall<TransactionReceipt> approve(String spender, BigInteger value) {
        final Function function = new Function(
                FUNC_APPROVE,
                Arrays.asList(new Address(spender), new Uint256(value)),
                Collections.emptyList());

        return executeRemoteCallTransaction(function);
    }

    // transfer方法实现
    public RemoteFunctionCall<TransactionReceipt> transfer(String to, BigInteger value) {
        final Function function = new Function(
                FUNC_TRANSFER,
                Arrays.asList(new Address(to), new Uint256(value)),
                Collections.emptyList());

        return executeRemoteCallTransaction(function);
    }

    // balanceOf方法实现（只读操作，使用call而不是transaction）
    public RemoteFunctionCall<BigInteger> balanceOf(String owner) {
        final Function function = new Function(
                FUNC_BALANCE_OF,
                Arrays.asList(new Address(owner)),
                Arrays.asList(new TypeReference<Uint256>() {}));

        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

    // 更通用的交易执行方法
    protected RemoteFunctionCall<TransactionReceipt> executeTransaction(
            String functionName, List<Type> inputParameters) {
        final Function function = new Function(
                functionName,
                inputParameters,
                Collections.emptyList());

        return executeRemoteCallTransaction(function);
    }

    // 使用原始Function对象执行交易
    protected RemoteFunctionCall<TransactionReceipt> executeRemoteCallTransaction(Function function) {
        return new RemoteFunctionCall<>(function,
                () -> executeTransaction(function));
    }
}
